home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Gfx / Edit / TSMorph / src / jpeg_ls / jrdppm.c < prev    next >
C/C++ Source or Header  |  1994-10-30  |  14KB  |  498 lines

  1. /*
  2.  * jrdppm.c
  3.  *
  4.  * Copyright (C) 1991, 1992, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to read input images in PPM format.
  9.  * The PBMPLUS library is NOT required to compile this software,
  10.  * but it is highly useful as a set of PPM image manipulation programs.
  11.  *
  12.  * These routines may need modification for non-Unix environments or
  13.  * specialized applications.  As they stand, they assume input from
  14.  * an ordinary stdio stream.  They further assume that reading begins
  15.  * at the start of the file; input_init may need work if the
  16.  * user interface has already read some data (e.g., to determine that
  17.  * the file is indeed PPM format).
  18.  *
  19.  * These routines are invoked via the methods get_input_row
  20.  * and input_init/term.
  21.  */
  22.  
  23. #include "jinclude.h"
  24.  
  25. #ifdef PPM_SUPPORTED
  26.  
  27.  
  28. /* Portions of this code are based on the PBMPLUS library, which is:
  29. **
  30. ** Copyright (C) 1988 by Jef Poskanzer.
  31. **
  32. ** Permission to use, copy, modify, and distribute this software and its
  33. ** documentation for any purpose and without fee is hereby granted, provided
  34. ** that the above copyright notice appear in all copies and that both that
  35. ** copyright notice and this permission notice appear in supporting
  36. ** documentation.  This software is provided "as is" without express or
  37. ** implied warranty.
  38. */
  39.  
  40.  
  41. /* Macros to deal with unsigned chars as efficiently as compiler allows */
  42.  
  43. #ifdef HAVE_UNSIGNED_CHAR
  44. typedef unsigned char U_CHAR;
  45. #define UCH(x)    ((int) (x))
  46. #else /* !HAVE_UNSIGNED_CHAR */
  47. #ifdef CHAR_IS_UNSIGNED
  48. typedef char U_CHAR;
  49. #define UCH(x)    ((int) (x))
  50. #else
  51. typedef char U_CHAR;
  52. #define UCH(x)    ((int) (x) & 0xFF)
  53. #endif
  54. #endif /* HAVE_UNSIGNED_CHAR */
  55.  
  56.  
  57. #define    ReadOK(file,buffer,len)    (JFREAD(file,buffer,len) == ((size_t) (len)))
  58.  
  59.  
  60. /*
  61.  * On most systems, reading individual bytes with getc() is drastically less
  62.  * efficient than buffering a row at a time with fread().  But we must
  63.  * allocate the row buffer in near data space on PCs, because we are assuming
  64.  * small-data memory model, wherein fread() can't reach far memory.  If you
  65.  * need to process very wide images on a PC, you may have to use the getc()
  66.  * approach.  In that case, define USE_GETC_INPUT.
  67.  */
  68.  
  69. #ifndef USE_GETC_INPUT
  70. static U_CHAR * row_buffer;    /* holds 1 pixel row's worth of raw input */
  71. #endif
  72.  
  73. static JSAMPLE * rescale;    /* => maxval-remapping array, or NULL */
  74.  
  75.  
  76. LOCAL int
  77. #ifdef AMIGA_IO
  78. pbm_getc (BPTR file)
  79. #else
  80. pbm_getc (FILE * file)
  81. #endif
  82. /* Read next char, skipping over any comments */
  83. /* A comment/newline sequence is returned as a newline */
  84. {
  85.   register int ch;
  86.   
  87.   ch = getc(file);
  88.   if (ch == '#') {
  89.     do {
  90.       ch = getc(file);
  91.     } while (ch != '\n' && ch != EOF);
  92.   }
  93.   return ch;
  94. }
  95.  
  96.  
  97. LOCAL unsigned int
  98. read_pbm_integer (decompress_info_ptr cinfo)
  99. /* Read an unsigned decimal integer from the PPM file */
  100. /* Swallows one trailing character after the integer */
  101. /* Note that on a 16-bit-int machine, only values up to 64k can be read. */
  102. /* This should not be a problem in practice. */
  103. {
  104.   register int ch;
  105.   register unsigned int val;
  106.   
  107.   /* Skip any leading whitespace */
  108.   do {
  109.     ch = pbm_getc(cinfo->input_file);
  110.     if (ch == EOF)
  111.       ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
  112.   } while (ch == ' ' || ch == '\t' || ch == '\n');
  113.   
  114.   if (ch < '0' || ch > '9')
  115.     ERREXIT(cinfo->emethods, "Bogus data in PPM file");
  116.   
  117.   val = ch - '0';
  118.   while ((ch = pbm_getc(cinfo->input_file)) >= '0' && ch <= '9') {
  119.     val *= 10;
  120.     val += ch - '0';
  121.   }
  122.   return val;
  123. }
  124.  
  125.  
  126. /*
  127.  * Read one row of pixels.
  128.  *
  129.  * We provide several different versions depending on input file format.
  130.  * In all cases, input is scaled to the size of JSAMPLE; it's possible that
  131.  * when JSAMPLE is 12 bits, this would not really be desirable.
  132.  *
  133.  * Note that a really fast path is provided for reading raw files with
  134.  * maxval = MAXJSAMPLE, which is the normal case (at least for 8-bit JSAMPLEs).
  135.  */
  136.  
  137.  
  138. METHODDEF void
  139. get_text_gray_row (decompress_info_ptr cinfo, JSAMPARRAY pixel_row)
  140. /* This version is for reading text-format PGM files with any maxval */
  141. {
  142.   register JSAMPROW ptr0;
  143.   register JSAMPROW ptr1;
  144.   register JSAMPROW ptr2;
  145.   register unsigned int val;
  146.   register long col;
  147.   
  148.   ptr0 = pixel_row[0];
  149.   ptr1 = pixel_row[1];
  150.   ptr2 = pixel_row[2];
  151.   for (col = cinfo->image_width; col > 0; col--) {
  152.     val = read_pbm_integer(cinfo);
  153.     if (rescale != NULL)
  154.       val = rescale[val];
  155.     *ptr0++ = (JSAMPLE) val;
  156.     *ptr1++ = (JSAMPLE) val;
  157.     *ptr2++ = (JSAMPLE) val;
  158.   }
  159. }
  160.  
  161.  
  162. METHODDEF void
  163. get_text_rgb_row (decompress_info_ptr cinfo, JSAMPARRAY pixel_row)
  164. /* This version is for reading text-format PPM files with any maxval */
  165. {
  166.   register JSAMPROW ptr0, ptr1, ptr2;
  167.   register unsigned int val;
  168.   register long col;
  169.   
  170.   ptr0 = pixel_row[0];
  171.   ptr1 = pixel_row[1];
  172.   ptr2 = pixel_row[2];
  173.   for (col = cinfo->image_width; col > 0; col--) {
  174.     val = read_pbm_integer(cinfo);
  175.     if (rescale != NULL)
  176.       val = rescale[val];
  177.     *ptr0++ = (JSAMPLE) val;
  178.     val = read_pbm_integer(cinfo);
  179.     if (rescale != NULL)
  180.       val = rescale[val];
  181.     *ptr1++ = (JSAMPLE) val;
  182.     val = read_pbm_integer(cinfo);
  183.     if (rescale != NULL)
  184.       val = rescale[val];
  185.     *ptr2++ = (JSAMPLE) val;
  186.   }
  187. }
  188.  
  189.  
  190. #ifdef USE_GETC_INPUT
  191.  
  192.  
  193. METHODDEF void
  194. get_scaled_gray_row (decompress_info_ptr cinfo, JSAMPARRAY pixel_row)
  195. /* This version is for reading raw-format PGM files with any maxval */
  196. {
  197.   register FILE * infile = cinfo->input_file;
  198.   register JSAMPROW ptr0;
  199.   register JSAMPROW ptr1;
  200.   register JSAMPROW ptr2;
  201.   register long col;
  202.   
  203.   ptr0 = pixel_row[0];
  204.   ptr1 = pixel_row[1];
  205.   ptr2 = pixel_row[2];
  206.   for (col = cinfo->image_width; col > 0; col--) {
  207.     *ptr0 = rescale[getc(infile)];
  208.     *ptr1++ = *ptr0;
  209.     *ptr2++ = *ptr0;
  210.     ptr0++;
  211.   }
  212. }
  213.  
  214.  
  215. METHODDEF void
  216. get_scaled_rgb_row (decompress_info_ptr cinfo, JSAMPARRAY pixel_row)
  217. /* This version is for reading raw-format PPM files with any maxval */
  218. {
  219.   register FILE * infile = cinfo->input_file;
  220.   register JSAMPROW ptr0, ptr1, ptr2;
  221.   register long col;
  222.   
  223.   ptr0 = pixel_row[0];
  224.   ptr1 = pixel_row[1];
  225.   ptr2 = pixel_row[2];
  226.   for (col = cinfo->image_width; col > 0; col--) {
  227.     *ptr0++ = rescale[getc(infile)];
  228.     *ptr1++ = rescale[getc(infile)];
  229.     *ptr2++ = rescale[getc(infile)];
  230.   }
  231. }
  232.  
  233.  
  234. METHODDEF void
  235. get_raw_gray_row (decompress_info_ptr cinfo, JSAMPARRAY pixel_row)
  236. /* This version is for reading raw-format PGM files with maxval = MAXJSAMPLE */
  237. {
  238.   register FILE * infile = cinfo->input_file;
  239.   register JSAMPROW ptr0;
  240.   register JSAMPROW ptr1;
  241.   register JSAMPROW ptr2;
  242.   register long col;
  243.   
  244.   ptr0 = pixel_row[0];
  245.   ptr1 = pixel_row[1];
  246.   ptr2 = pixel_row[2];
  247.   for (col = cinfo->image_width; col > 0; col--) {
  248.     *ptr0 = (JSAMPLE) getc(infile);
  249.     *ptr1++ = *ptr0;
  250.     *ptr2++ = *ptr0;
  251.     ptr0++;
  252.   }
  253. }
  254.  
  255.  
  256. METHODDEF void
  257. get_raw_rgb_row (decompress_info_ptr cinfo, JSAMPARRAY pixel_row)
  258. /* This version is for reading raw-format PPM files with maxval = MAXJSAMPLE */
  259. {
  260.   register FILE * infile = cinfo->input_file;
  261.   register JSAMPROW ptr0, ptr1, ptr2;
  262.   register long col;
  263.   
  264.   ptr0 = pixel_row[0];
  265.   ptr1 = pixel_row[1];
  266.   ptr2 = pixel_row[2];
  267.   for (col = cinfo->image_width; col > 0; col--) {
  268.     *ptr0++ = (JSAMPLE) getc(infile);
  269.     *ptr1++ = (JSAMPLE) getc(infile);
  270.     *ptr2++ = (JSAMPLE) getc(infile);
  271.   }
  272. }
  273.  
  274.  
  275. #else /* use row buffering */
  276.  
  277.  
  278. METHODDEF void
  279. get_scaled_gray_row (decompress_info_ptr cinfo, JSAMPARRAY pixel_row)
  280. /* This version is for reading raw-format PGM files with any maxval */
  281. {
  282.   register JSAMPROW ptr0;
  283.   register JSAMPROW ptr1;
  284.   register JSAMPROW ptr2;
  285.   register U_CHAR * row_bufferptr;
  286.   register long col;
  287.   
  288.   if (! ReadOK(cinfo->input_file, row_buffer, cinfo->image_width))
  289.     ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
  290.   ptr0 = pixel_row[0];
  291.   ptr1 = pixel_row[1];
  292.   ptr2 = pixel_row[2];
  293.   row_bufferptr = row_buffer;
  294.   for (col = cinfo->image_width; col > 0; col--) {
  295.     *ptr0 = rescale[UCH(*row_bufferptr++)];
  296.     *ptr1++ = *ptr0;
  297.     *ptr2++ = *ptr0;
  298.     ptr0++;
  299.   }
  300. }
  301.  
  302.  
  303. METHODDEF void
  304. get_scaled_rgb_row (decompress_info_ptr cinfo, JSAMPARRAY pixel_row)
  305. /* This version is for reading raw-format PPM files with any maxval */
  306. {
  307.   register JSAMPROW ptr0, ptr1, ptr2;
  308.   register U_CHAR * row_bufferptr;
  309.   register long col;
  310.   
  311.   if (! ReadOK(cinfo->input_file, row_buffer, 3 * cinfo->image_width))
  312.     ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
  313.   ptr0 = pixel_row[0];
  314.   ptr1 = pixel_row[1];
  315.   ptr2 = pixel_row[2];
  316.   row_bufferptr = row_buffer;
  317.   for (col = cinfo->image_width; col > 0; col--) {
  318.     *ptr0++ = rescale[UCH(*row_bufferptr++)];
  319.     *ptr1++ = rescale[UCH(*row_bufferptr++)];
  320.     *ptr2++ = rescale[UCH(*row_bufferptr++)];
  321.   }
  322. }
  323.  
  324.  
  325. METHODDEF void
  326. get_raw_gray_row (decompress_info_ptr cinfo, JSAMPARRAY pixel_row)
  327. /* This version is for reading raw-format PGM files with maxval = MAXJSAMPLE */
  328. {
  329.   register JSAMPROW ptr0;
  330.   register JSAMPROW ptr1;
  331.   register JSAMPROW ptr2;
  332.   register U_CHAR * row_bufferptr;
  333.   register long col;
  334.   
  335.   if (! ReadOK(cinfo->input_file, row_buffer, cinfo->image_width))
  336.     ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
  337.   ptr0 = pixel_row[0];
  338.   ptr1 = pixel_row[1];
  339.   ptr2 = pixel_row[2];
  340.   row_bufferptr = row_buffer;
  341.   for (col = cinfo->image_width; col > 0; col--) {
  342.     *ptr0 = (JSAMPLE) UCH(*row_bufferptr++);
  343.     *ptr1++ = *ptr0;
  344.     *ptr2++ = *ptr0;
  345.     ptr0++;
  346.   }
  347. }
  348.  
  349.  
  350. METHODDEF void
  351. get_raw_rgb_row (decompress_info_ptr cinfo, JSAMPARRAY pixel_row)
  352. /* This version is for reading raw-format PPM files with maxval = MAXJSAMPLE */
  353. {
  354.   register JSAMPROW ptr0, ptr1, ptr2;
  355.   register U_CHAR * row_bufferptr;
  356.   register long col;
  357.   
  358.   if (! ReadOK(cinfo->input_file, row_buffer, 3 * cinfo->image_width))
  359.     ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
  360.   ptr0 = pixel_row[0];
  361.   ptr1 = pixel_row[1];
  362.   ptr2 = pixel_row[2];
  363.   row_bufferptr = row_buffer;
  364.   for (col = cinfo->image_width; col > 0; col--) {
  365.     *ptr0++ = (JSAMPLE) UCH(*row_bufferptr++);
  366.     *ptr1++ = (JSAMPLE) UCH(*row_bufferptr++);
  367.     *ptr2++ = (JSAMPLE) UCH(*row_bufferptr++);
  368.   }
  369. }
  370.  
  371.  
  372. #endif /* USE_GETC_INPUT */
  373.  
  374.  
  375. /*
  376.  * Read the file header; return image size and component count.
  377.  */
  378.  
  379. METHODDEF void
  380. input_init (decompress_info_ptr cinfo)
  381. {
  382.   int c;
  383.   unsigned int w, h, maxval;
  384.  
  385.   if (getc(cinfo->input_file) != 'P')
  386.     ERREXIT(cinfo->emethods, "Not a PPM file");
  387.  
  388.   c = getc(cinfo->input_file);    /* save format discriminator for a sec */
  389.  
  390.   w = read_pbm_integer(cinfo);    /* while we fetch the header info */
  391.   h = read_pbm_integer(cinfo);
  392.   maxval = read_pbm_integer(cinfo);
  393.  
  394.   if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
  395.     ERREXIT(cinfo->emethods, "Not a PPM file");
  396.  
  397.   switch (c) {
  398.   case '2':            /* it's a text-format PGM file */
  399.     cinfo->methods->get_input_row = get_text_gray_row;
  400.     cinfo->input_components = 1;
  401.     cinfo->in_color_space = CS_GRAYSCALE;
  402.     TRACEMS2(cinfo->emethods, 1, "%ldx%ld text PGM image", w, h);
  403.     break;
  404.  
  405.   case '3':            /* it's a text-format PPM file */
  406.     cinfo->methods->get_input_row = get_text_rgb_row;
  407.     cinfo->input_components = 3;
  408.     cinfo->in_color_space = CS_RGB;
  409.     TRACEMS2(cinfo->emethods, 1, "%ldx%ld text PPM image", w, h);
  410.     break;
  411.  
  412.   case '5':            /* it's a raw-format PGM file */
  413.     if (maxval == MAXJSAMPLE)
  414.       cinfo->methods->get_input_row = get_raw_gray_row;
  415.     else
  416.       cinfo->methods->get_input_row = get_scaled_gray_row;
  417.     cinfo->input_components = 1;
  418.     cinfo->in_color_space = CS_GRAYSCALE;
  419. #ifndef USE_GETC_INPUT
  420.     /* allocate space for row buffer: 1 byte/pixel */
  421.     row_buffer = (U_CHAR *) (*cinfo->emethods->alloc_small)
  422.             ((size_t) (SIZEOF(U_CHAR) * (long) w));
  423. #endif
  424.     TRACEMS2(cinfo->emethods, 1, "%ldx%ld PGM image", w, h);
  425.     break;
  426.  
  427.   case '6':            /* it's a raw-format PPM file */
  428.     if (maxval == MAXJSAMPLE)
  429.       cinfo->methods->get_input_row = get_raw_rgb_row;
  430.     else
  431.       cinfo->methods->get_input_row = get_scaled_rgb_row;
  432.     cinfo->input_components = 3;
  433.     cinfo->in_color_space = CS_RGB;
  434. #ifndef USE_GETC_INPUT
  435.     /* allocate space for row buffer: 3 bytes/pixel */
  436.     row_buffer = (U_CHAR *) (*cinfo->emethods->alloc_small)
  437.             ((size_t) (3 * SIZEOF(U_CHAR) * (long) w));
  438. #endif
  439.     TRACEMS2(cinfo->emethods, 1, "%ldx%ld PPM image", w, h);
  440.     break;
  441.  
  442.   default:
  443.     ERREXIT(cinfo->emethods, "Not a PPM file");
  444.     break;
  445.   }
  446.  
  447.   /* Compute the rescaling array if necessary */
  448.   /* This saves per-pixel calculation */
  449.   if (maxval == MAXJSAMPLE)
  450.     rescale = NULL;        /* no rescaling required */
  451.   else {
  452.     INT32 val, half_maxval;
  453.  
  454.     /* On 16-bit-int machines we have to be careful of maxval = 65535 */
  455.     rescale = (JSAMPLE *) (*cinfo->emethods->alloc_small)
  456.             ((size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE)));
  457.     half_maxval = maxval / 2;
  458.     for (val = 0; val <= (INT32) maxval; val++) {
  459.       /* The multiplication here must be done in 32 bits to avoid overflow */
  460.       rescale[val] = (JSAMPLE) ((val * MAXJSAMPLE + half_maxval) / maxval);
  461.     }
  462.   }
  463.  
  464.   cinfo->image_width = w;
  465.   cinfo->image_height = h;
  466.   cinfo->data_precision = BITS_IN_JSAMPLE;
  467. }
  468.  
  469.  
  470. /*
  471.  * Finish up at the end of the file.
  472.  */
  473.  
  474. METHODDEF void
  475. input_term (decompress_info_ptr cinfo)
  476. {
  477.   /* no work (we let free_all release the workspace) */
  478. }
  479.  
  480.  
  481. /*
  482.  * The method selection routine for PPM format input.
  483.  * Note that this must be called by the user interface before calling
  484.  * jpeg_compress.  If multiple input formats are supported, the
  485.  * user interface is responsible for discovering the file format and
  486.  * calling the appropriate method selection routine.
  487.  */
  488.  
  489. GLOBAL void
  490. jselrppm (decompress_info_ptr cinfo)
  491. {
  492.   cinfo->methods->input_init = input_init;
  493.   /* cinfo->methods->get_input_row is set by input_init */
  494.   cinfo->methods->input_term = input_term;
  495. }
  496.  
  497. #endif /* PPM_SUPPORTED */
  498.